package com.zfdang.touchhelper.tool;

import android.accessibilityservice.AccessibilityService;
import android.app.Service;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.aivin.adovertool.R;
import com.zfdang.touchhelper.bean.PackagePositionInfoBean;
import com.zfdang.touchhelper.bean.PackageWidgetInfoBean;
import com.zfdang.touchhelper.callback.IwindowResultCallback;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author Aivin
 * created on 2023/11/9
 * des:
 */
public class LyWindowTool {
    private final WindowManager windowManager;
    private final IwindowResultCallback callback;
    private final AccessibilityService accessibilityService;
    private final LayoutInflater inflater;
    private final WindowManager.LayoutParams customizationParams, outlineParams, targetParams;

    public LyWindowTool(Context context, IwindowResultCallback callback, AccessibilityService accessibilityService) {
        inflater = LayoutInflater.from(accessibilityService);
        windowManager = (WindowManager) context.getSystemService(AccessibilityService.WINDOW_SERVICE);
        this.callback = callback;
        this.accessibilityService = accessibilityService;
        customizationParams = getCustomizationParams(accessibilityService);
        outlineParams = getOutlineParams(accessibilityService);
        targetParams = getTargetParams(accessibilityService);
    }


    public void showActivityCustomizationDialog(
            String currentPackageName,
            String currentActivityName,
            Map<String, PackagePositionInfoBean> mapPackagePositions,
            Map<String, Set<PackageWidgetInfoBean>> mapPackageWidgets
    ) {
        // 用来取坐标的图标
        final ImageView imageTarget = new ImageView(accessibilityService);
        imageTarget.setImageResource(R.drawable.ic_target);

        // 绘制当前页面控件轮廓的容器
        View viewTarget = inflater.inflate(R.layout.layout_accessibility_node_desc, null);
        ;
        final FrameLayout layoutOverlayOutline = viewTarget.findViewById(R.id.frame);

        // 显示当前获取到的信息的面板
        View viewCustomization = initInfoPanel(inflater, imageTarget,
                layoutOverlayOutline,
                viewTarget,
                currentPackageName,
                currentActivityName,
                mapPackagePositions,
                mapPackageWidgets
        );

        windowManager.addView(viewTarget, outlineParams);
        windowManager.addView(viewCustomization, customizationParams);
        windowManager.addView(imageTarget, targetParams);
        callback.onWindowShow(true);
    }


    private View initInfoPanel(LayoutInflater inflater,
                               ImageView imageTarget,
                               FrameLayout layoutOverlayOutline,
                               View viewTarget, String currentPackageName,
                               String currentActivityName,
                               Map<String, PackagePositionInfoBean> mapPackagePositions,
                               Map<String, Set<PackageWidgetInfoBean>> mapPackageWidgets) {

        final View viewCustomization = inflater.inflate(R.layout.layout_activity_customization, null);
        final TextView tvPackageName = viewCustomization.findViewById(R.id.tv_package_name);
        final TextView tvActivityName = viewCustomization.findViewById(R.id.tv_activity_name);
        final TextView tvWidgetInfo = viewCustomization.findViewById(R.id.tv_widget_info);
        final TextView tvPositionInfo = viewCustomization.findViewById(R.id.tv_position_info);
        Button btShowOutline = viewCustomization.findViewById(R.id.button_show_outline);
        final Button btAddWidget = viewCustomization.findViewById(R.id.button_add_widget);
        Button btShowTarget = viewCustomization.findViewById(R.id.button_show_target);
        final Button btAddPosition = viewCustomization.findViewById(R.id.button_add_position);

        Button btQuit = viewCustomization.findViewById(R.id.button_quit);

        final PackageWidgetInfoBean widgetDescription = new PackageWidgetInfoBean();
        final PackagePositionInfoBean positionDescription = new PackagePositionInfoBean();

        viewCustomization.setOnTouchListener(new View.OnTouchListener() {
            int x = 0, y = 0;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        x = Math.round(event.getRawX());
                        y = Math.round(event.getRawY());
                        break;
                    case MotionEvent.ACTION_MOVE:
                        customizationParams.x = Math.round(customizationParams.x + (event.getRawX() - x));
                        customizationParams.y = Math.round(customizationParams.y + (event.getRawY() - y));
                        x = Math.round(event.getRawX());
                        y = Math.round(event.getRawY());
                        windowManager.updateViewLayout(viewCustomization, customizationParams);
                        break;
                }
                return true;
            }
        });

        imageTarget.setOnTouchListener(new View.OnTouchListener() {
            int x = 0, y = 0, width = targetParams.width / 2, height = targetParams.height / 2;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        btAddPosition.setEnabled(true);
                        targetParams.alpha = 0.9f;
                        windowManager.updateViewLayout(imageTarget, targetParams);
                        x = Math.round(event.getRawX());
                        y = Math.round(event.getRawY());
                        break;
                    case MotionEvent.ACTION_MOVE:
                        targetParams.x = Math.round(targetParams.x + (event.getRawX() - x));
                        targetParams.y = Math.round(targetParams.y + (event.getRawY() - y));
                        x = Math.round(event.getRawX());
                        y = Math.round(event.getRawY());
                        windowManager.updateViewLayout(imageTarget, targetParams);
                        positionDescription.packageName = currentPackageName;
                        positionDescription.activityName = currentActivityName;
                        positionDescription.x = targetParams.x + width;
                        positionDescription.y = targetParams.y + height;
                        tvPackageName.setText(positionDescription.packageName);
                        tvActivityName.setText(positionDescription.activityName);
                        tvPositionInfo.setText("X轴：" + positionDescription.x + "    " + "Y轴：" + positionDescription.y + "    " + "(其他参数默认)");
                        break;
                    case MotionEvent.ACTION_UP:
                        targetParams.alpha = 0.5f;
                        windowManager.updateViewLayout(imageTarget, targetParams);
                        break;
                }
                return true;
            }
        });

        btShowOutline.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Button button = (Button) v;
                if (outlineParams.alpha == 0) {
                    AccessibilityNodeInfo root = accessibilityService.getRootInActiveWindow();
                    if (root == null) {
                        return;
                    }
                    widgetDescription.packageName = currentPackageName;
                    widgetDescription.activityName = currentActivityName;
                    layoutOverlayOutline.removeAllViews();
                    ArrayList<AccessibilityNodeInfo> roots = new ArrayList<>();
                    roots.add(root);
                    ArrayList<AccessibilityNodeInfo> nodeList = new ArrayList<>();
                    callback.needFindAllNode(roots, nodeList, "");
                    Collections.sort(nodeList, new Comparator<AccessibilityNodeInfo>() {
                        @Override
                        public int compare(AccessibilityNodeInfo a, AccessibilityNodeInfo b) {
                            Rect rectA = new Rect();
                            Rect rectB = new Rect();
                            a.getBoundsInScreen(rectA);
                            b.getBoundsInScreen(rectB);
                            return rectB.width() * rectB.height() - rectA.width() * rectA.height();
                        }
                    });
                    for (final AccessibilityNodeInfo e : nodeList) {
                        final Rect temRect = new Rect();
                        e.getBoundsInScreen(temRect);
                        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(temRect.width(), temRect.height());
                        params.leftMargin = temRect.left;
                        params.topMargin = temRect.top;
                        final ImageView img = new ImageView(accessibilityService);
                        img.setBackgroundResource(R.drawable.node);
                        img.setFocusableInTouchMode(true);
                        img.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                v.requestFocus();
                            }
                        });
                        img.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                            @Override
                            public void onFocusChange(View v, boolean hasFocus) {
                                if (hasFocus) {
                                    widgetDescription.position = temRect;
                                    widgetDescription.clickable = e.isClickable();
                                    widgetDescription.className = e.getClassName().toString();
                                    CharSequence cId = e.getViewIdResourceName();
                                    widgetDescription.idName = cId == null ? "" : cId.toString();
                                    CharSequence cDesc = e.getContentDescription();
                                    widgetDescription.description = cDesc == null ? "" : cDesc.toString();
                                    CharSequence cText = e.getText();
                                    widgetDescription.text = cText == null ? "" : cText.toString();
                                    btAddWidget.setEnabled(true);
                                    tvPackageName.setText(widgetDescription.packageName);
                                    tvActivityName.setText(widgetDescription.activityName);
                                    tvWidgetInfo.setText("click:" + (e.isClickable() ? "true" : "false") + " " + "bonus:" + temRect.toShortString() + " " + "id:" + (cId == null ? "null" : cId.toString().substring(cId.toString().indexOf("id/") + 3)) + " " + "desc:" + (cDesc == null ? "null" : cDesc.toString()) + " " + "text:" + (cText == null ? "null" : cText.toString()));
                                    v.setBackgroundResource(R.drawable.node_focus);
                                } else {
                                    v.setBackgroundResource(R.drawable.node);
                                }
                            }
                        });
                        layoutOverlayOutline.addView(img, params);
                    }
                    outlineParams.alpha = 0.5f;
                    outlineParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
                    windowManager.updateViewLayout(viewTarget, outlineParams);
                    tvPackageName.setText(widgetDescription.packageName);
                    tvActivityName.setText(widgetDescription.activityName);
                    button.setText("隐藏布局");
                } else {
                    outlineParams.alpha = 0f;
                    outlineParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
                    windowManager.updateViewLayout(viewTarget, outlineParams);
                    btAddWidget.setEnabled(false);
                    button.setText("显示布局");
                }
            }
        });
        btShowTarget.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Button button = (Button) v;
                if (targetParams.alpha == 0) {
                    positionDescription.packageName = currentPackageName;
                    positionDescription.activityName = currentActivityName;
                    targetParams.alpha = 0.5f;
                    targetParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
                    windowManager.updateViewLayout(imageTarget, targetParams);
                    tvPackageName.setText(positionDescription.packageName);
                    tvActivityName.setText(positionDescription.activityName);
                    button.setText("隐藏准心");
                } else {
                    targetParams.alpha = 0f;
                    targetParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
                    windowManager.updateViewLayout(imageTarget, targetParams);
                    btAddPosition.setEnabled(false);
                    button.setText("显示准心");
                }
            }
        });
        btAddWidget.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PackageWidgetInfoBean temWidget = new PackageWidgetInfoBean(widgetDescription);
                Set<PackageWidgetInfoBean> set = mapPackageWidgets.get(widgetDescription.packageName);
                if (set == null) {
                    set = new HashSet<>();
                    set.add(temWidget);
                    mapPackageWidgets.put(widgetDescription.packageName, set);
                } else {
                    set.add(temWidget);
                }
                btAddWidget.setEnabled(false);
                tvPackageName.setText(widgetDescription.packageName + " (以下控件数据已保存)");
                // save
                SettingsTool.getInstance().setPackageWidgets(mapPackageWidgets);
            }
        });
        btAddPosition.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mapPackagePositions.put(positionDescription.packageName, new PackagePositionInfoBean(positionDescription));
                btAddPosition.setEnabled(false);
                tvPackageName.setText(positionDescription.packageName + " (以下坐标数据已保存)");
                // save
                SettingsTool.getInstance().setPackagePositions(mapPackagePositions);
            }
        });

        viewCustomization.findViewById(R.id.button_dump_screen).setOnClickListener(v -> {
            AccessibilityNodeInfo root = accessibilityService.getRootInActiveWindow();
            if (root == null) {
                LyLog.showLog("root is null....");
                return;
            }
            String result = callback.needDumpRootNode(root);
            LyLog.showLog("1 result==="+result);
            ClipboardManager clipboard = (ClipboardManager) accessibilityService.getSystemService(Context.CLIPBOARD_SERVICE);
            ClipData clip = ClipData.newPlainText("ACTIVITY", result);
            clipboard.setPrimaryClip(clip);
            LyLog.showLog("2 result==="+result);
            callback.needToastMsg("窗口控件已复制到剪贴板！");
        });

        btQuit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                windowManager.removeViewImmediate(viewTarget);
                windowManager.removeViewImmediate(viewCustomization);
                windowManager.removeViewImmediate(imageTarget);
                callback.onWindowShow(false);
            }
        });
        return viewCustomization;
    }


    private WindowManager.LayoutParams getCustomizationParams(Context context) {
        final WindowManager windowManager = (WindowManager) context.getSystemService(AccessibilityService.WINDOW_SERVICE);
        final DisplayMetrics metrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getRealMetrics(metrics);
        boolean b = metrics.heightPixels > metrics.widthPixels;
        final int width = b ? metrics.widthPixels : metrics.heightPixels;
        final int height = b ? metrics.heightPixels : metrics.widthPixels;
        //----------

        final WindowManager.LayoutParams customizationParams = new WindowManager.LayoutParams();
        customizationParams.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
        customizationParams.format = PixelFormat.TRANSPARENT;
        customizationParams.gravity = Gravity.START | Gravity.TOP;
        customizationParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        customizationParams.width = width;
        customizationParams.height = height / 5;
        customizationParams.x = (metrics.widthPixels - customizationParams.width) / 2;
        customizationParams.y = metrics.heightPixels - customizationParams.height;
        customizationParams.alpha = 0.8f;
        return customizationParams;
    }

    private WindowManager.LayoutParams getOutlineParams(Context context) {
        final WindowManager windowManager = (WindowManager) context.getSystemService(AccessibilityService.WINDOW_SERVICE);
        final DisplayMetrics metrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getRealMetrics(metrics);
        boolean b = metrics.heightPixels > metrics.widthPixels;
        final int width = b ? metrics.widthPixels : metrics.heightPixels;
        final int height = b ? metrics.heightPixels : metrics.widthPixels;
        //----------

        WindowManager.LayoutParams outlineParams = new WindowManager.LayoutParams();
        outlineParams.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
        outlineParams.format = PixelFormat.TRANSPARENT;
        outlineParams.gravity = Gravity.START | Gravity.TOP;
        outlineParams.width = metrics.widthPixels;
        outlineParams.height = metrics.heightPixels;
        outlineParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        outlineParams.alpha = 0f;
        return outlineParams;
    }

    private WindowManager.LayoutParams getTargetParams(Context context) {
        final WindowManager windowManager = (WindowManager) context.getSystemService(AccessibilityService.WINDOW_SERVICE);
        final DisplayMetrics metrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getRealMetrics(metrics);
        boolean b = metrics.heightPixels > metrics.widthPixels;
        final int width = b ? metrics.widthPixels : metrics.heightPixels;
        final int height = b ? metrics.heightPixels : metrics.widthPixels;
        //----------

        WindowManager.LayoutParams targetParams = new WindowManager.LayoutParams();
        targetParams.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
        targetParams.format = PixelFormat.TRANSPARENT;
        targetParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        targetParams.gravity = Gravity.START | Gravity.TOP;
        targetParams.width = targetParams.height = width / 4;
        targetParams.x = (metrics.widthPixels - targetParams.width) / 2;
        targetParams.y = (metrics.heightPixels - targetParams.height) / 2;
        targetParams.alpha = 0f;
        return targetParams;
    }


}
